package edu.zcmu.seckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.interfaces.DecodedJWT;
import edu.zcmu.seckill.entity.*;
import edu.zcmu.seckill.enumeration.GlobalEnum;
import edu.zcmu.seckill.enumeration.OrderStatusEnum;
import edu.zcmu.seckill.exception.MyException;
import edu.zcmu.seckill.mapper.SeckillProductMapper;
import edu.zcmu.seckill.response.ResultCode;
import edu.zcmu.seckill.service.*;
import edu.zcmu.seckill.utils.JwtUtil;
import edu.zcmu.seckill.vo.PayVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Service
public class PayServiceImpl implements PayService {

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    JwtUtil jwtUtil;
    @Autowired
    ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    UserService userService;
    @Autowired
    SeckillOrderService seckillOrderService;
    @Autowired
    SysBankService sysBankService;
    @Autowired
    SeckillOrderPayLogService seckillOrderPayLogService;

    @Autowired
    SeckillProductMapper seckillProductMapper;

    @Transactional
    @Override
    public synchronized Boolean pay(PayVo payVo, HttpServletRequest request) {

        if (payVo==null){
            throw new MyException(ResultCode.ERROR,"当前系统状态异常");
        }
        String orderId = payVo.getOrderId();
        String productId = payVo.getProductId();
        //获取用户token
        DecodedJWT tokenInfo = JwtUtil.getTokenInfo(request.getHeader(jwtUtil.getHeader()));
        String uid = tokenInfo.getClaim("id").asString();  //获得token中携带的用户id
        if (StringUtils.isEmpty(uid)){
            throw new MyException(ResultCode.ERROR,"用户账号异常，请重新登录");
        }
        SeckillOrder seckillOrder = seckillOrderService.querySeckillOrder(orderId, productId, uid);
        if (seckillOrder==null){
            throw  new MyException(ResultCode.ERROR,"订单异常，请联系客服");
        }
        Integer orderStatus = seckillOrder.getOrderStatus();
        //判断订单状态
        if (orderStatus!=0){
            throw  new MyException(ResultCode.ERROR,"订单异常，请联系客服");
        }
        String o = (String) redisTemplate.opsForValue().get(GlobalEnum.GET_SECKILL_PRODUCT_REDIS.getCode() + productId);
        SeckillProduct product = JSON.parseObject(o, SeckillProduct.class);
        Boolean aBoolean = runPay(seckillOrder,uid, payVo, product.getPrice());
        if (!aBoolean){
            throw  new MyException(ResultCode.ERROR,"余额不足");
        }
        //过期时间设置为永久
        redisTemplate.persist(GlobalEnum.USER_SECKILL_PRODUCT_IS.getCode() + uid + ":" + payVo.getProductId());
        redisTemplate.persist(GlobalEnum.USER_SECKILL_PRODUCT_IS_EXPIRATION.getCode() + uid + ":" + payVo.getProductId()+":"+payVo.getOrderId());
        return true;
    }

    @Transactional
    public  Boolean runPay(SeckillOrder order,String uid, PayVo payVo, BigDecimal price){
        User byId = userService.getById(uid);
        if (price==null||byId.getMoney()==null||byId.getMoney().compareTo(price)==-1){
            return false;
        }else {
            //修改用户金额
            User user = new User();
            user.setId(Integer.valueOf(uid));
            user.setMoney(byId.getMoney().subtract(price));
            userService.updateUser(user);
            //更改银行金额
            SysBank sysBank = new SysBank();
            sysBank.setBankName("三湘银行");
            sysBank.setUpdateTime( new Date());
            sysBank.setBankMoney(price);
            sysBankService.updateByMoney(sysBank);
            //更改订单状态
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setOrderId(payVo.getOrderId());
            seckillOrder.setUserId(Integer.valueOf(uid));
            seckillOrder.setSeckillId(Integer.valueOf(payVo.getProductId()));
            seckillOrder.setOrderStatus(OrderStatusEnum.ORDER_PAID.getCode());
            seckillOrderService.updateSeckillOrder(seckillOrder);

            seckillProductMapper.updateProductBySale(payVo.getProductId(), 1);
            //添加支付日志
            threadPoolExecutor.execute(()->{
                SeckillOrderPayLog seckillOrderPayLog = new SeckillOrderPayLog();
                seckillOrderPayLog.setPrimaryId(order.getId());
                seckillOrderPayLog.setOrderId(payVo.getOrderId());
                seckillOrderPayLog.setToalFee(price);
                seckillOrderPayLog.setPayTime(new Date(System.currentTimeMillis()));
                seckillOrderPayLog.setPayType(1);
                seckillOrderPayLog.setCreateTime(new Date(System.currentTimeMillis()));
                seckillOrderPayLogService.addSeckillLog(seckillOrderPayLog);
            });
            return true;
        }
    }
}
